package com.jinbooks.web.oauth2.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjectUtil;
import com.jinbooks.authn.dto.SocialLoginBody;
import com.jinbooks.autoconfigure.SocialConfig;
import com.jinbooks.entity.Message;
import com.jinbooks.persistence.service.LoginService;
import com.jinbooks.util.JsonUtils;
import com.jinbooks.web.oauth2.social.properties.SocialLoginConfigProperties;
import com.jinbooks.web.oauth2.social.properties.SocialProperties;
import com.jinbooks.web.oauth2.social.utils.SocialUtils;
import com.jinbooks.web.satoken.utils.LoginHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping
@RequiredArgsConstructor
@Slf4j
public class Oauth2Controller {

    @Autowired
    LoginService loginService;
    @Autowired
    SocialProperties socialProperties;
    @Autowired
    SocialConfig socialConfig;

    /**
     * 获取跳转URL
     *
     * @param source 登录来源
     * @return 结果
     */
    @GetMapping("/binding/{source}")
    public Message<String> authBinding(@PathVariable("source") String source,
                                       @RequestParam String tenantId, @RequestParam String domain) {
        // 改造为从缓存获取最新配置
        SocialLoginConfigProperties obj = getSocialLoginConfigProperties(source);
        if (ObjectUtil.isNull(obj)) {
            return new Message<>(Message.FAIL, source + "平台账号暂不支持");
        }
        AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties);
        Map<String, String> map = new HashMap<>();
        map.put("tenantId", tenantId);
        map.put("domain", domain);
        map.put("state", AuthStateUtils.createState());
        String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8));
        return new Message<>(authorizeUrl);
    }

    /**
     * 前端回调绑定授权(需要token)
     *
     * @param loginBody 请求体
     * @return 结果
     */
    @PostMapping("/social/callback")
    public Message<Void> socialCallback(@RequestBody SocialLoginBody loginBody) {
        // 校验token
        StpUtil.checkLogin();
        // 获取第三方登录信息
        AuthResponse<AuthUser> response = SocialUtils.loginAuth(
                loginBody.getSource(), loginBody.getSocialCode(),
                loginBody.getSocialState(), socialProperties);
        AuthUser authUserData = response.getData();
        // 判断授权响应是否成功
        if (!response.ok()) {
            return new Message<>(Message.FAIL, response.getMsg());
        }
        String tenantId = LoginHelper.getTenantId();
        Long userId = LoginHelper.getUserId();
        loginService.socialRegister(authUserData, tenantId, userId);
        return new Message<>();
    }

    /**
     * 取消授权(需要token)
     *
     * @param socialId socialId
     */
    @DeleteMapping(value = "/unlock/{socialId}")
    public Message<Void> unlockSocial(@PathVariable Long socialId) {
        // 校验token
        StpUtil.checkLogin();
        Boolean rows = false;//socialUserService.deleteWithValidById(socialId);
        return rows ? Message.ok() : Message.failed("取消授权失败");
    }

    /**
     * 从缓存获取社交登录配置，如果缓存中没有则从数据库加载
     *
     * @param source 登录来源
     * @return 社交登录配置
     */
    private SocialLoginConfigProperties getSocialLoginConfigProperties(String source) {
        // 直接从SocialConfig缓存中获取最新的配置
        return socialConfig.getSocialLoginConfig(source);
    }

}